#ifndef __QUANTITY_H__
#define __QUANTITY_H__
#include <Unit.h>
#include <QuantityFormator.h>
#include <iostream>
using namespace std;

template <class T> class Quantity
{
typedef ostream & (*outputFormator) (ostream & out, unsigned long amount, const T &unit);

public:
    Quantity(unsigned long amount, const T &unit);
    bool operator == (const Quantity &quantity) const;
    Quantity operator + (const Quantity &quantity) const;
    ostream & operator << (ostream & out) const;
    ostream & output(ostream & out, outputFormator formator = QuantityFormatorInStdFormat<T>) const;

private:
    unsigned long getValue() const;
    unsigned long m_amount;
    T m_unit;
};

template <class T>
ostream& operator << (ostream& out, const Quantity <T>& quantity);

template <class T> 
Quantity<T>::Quantity(unsigned long amount, const T &unit) : m_amount(amount), m_unit(unit)
{
}

template <class T> 
bool Quantity<T>::operator == (const Quantity &quantity)const
{
     return (getValue() == quantity.getValue());
}

template <class T> 
Quantity<T> Quantity<T>::operator + (const Quantity<T> &quantity)const
{
    return Quantity<T>((getValue() + quantity.getValue()) / m_unit.baseUnit().factor(), \
        m_unit.baseUnit());
}

template <class T> 
ostream & Quantity<T>::operator << (ostream & out) const
{
    return output(out);
}

template <class T> 
unsigned long Quantity<T>::getValue() const
{
    return m_amount * m_unit.factor();
}

template <class T> 
ostream & Quantity<T>::output(ostream & out, outputFormator formator) const
{
    return formator(out, m_amount, m_unit);
}

template <class T>
ostream& operator << (ostream& out, const Quantity <T>& quantity)
{
    return quantity << (out);
}

#endif


